package com.petdog.common.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;

/**
 * 文件上传工具类
 * 提供文件上传、访问URL生成等功能
 */
@Component
public class FileUploadUtil {
    /**
     * 文件上传结果类
     */
    public static class FileUploadResult {
        private String url;
        private String fileId;
        private String originalFilename;
        private String storagePath;
        private String mimeType;
        private Long fileSize;
        
        public FileUploadResult(String url) {
            this.url = url;
        }
        
        public FileUploadResult(String url, String fileId, String originalFilename, String storagePath, String mimeType, Long fileSize) {
            this.url = url;
            this.fileId = fileId;
            this.originalFilename = originalFilename;
            this.storagePath = storagePath;
            this.mimeType = mimeType;
            this.fileSize = fileSize;
        }
        
        public String getUrl() {
            return url;
        }
        
        public void setUrl(String url) {
            this.url = url;
        }
        
        public String getFileId() {
            return fileId;
        }
        
        public void setFileId(String fileId) {
            this.fileId = fileId;
        }
        
        public String getOriginalFilename() {
            return originalFilename;
        }
        
        public void setOriginalFilename(String originalFilename) {
            this.originalFilename = originalFilename;
        }
        
        public String getStoragePath() {
            return storagePath;
        }
        
        public void setStoragePath(String storagePath) {
            this.storagePath = storagePath;
        }
        
        public String getMimeType() {
            return mimeType;
        }
        
        public void setMimeType(String mimeType) {
            this.mimeType = mimeType;
        }
        
        public Long getFileSize() {
            return fileSize;
        }
        
        public void setFileSize(Long fileSize) {
            this.fileSize = fileSize;
        }
    }
    private static final Logger logger = LoggerFactory.getLogger(FileUploadUtil.class);
    
    // 从配置文件读取参数
    @Value("${spring.file.upload.max-size}")
    private Long maxFileSize;
    
    @Value("${spring.file.upload.min-size}")
    private Long minFileSize;
    
    @Value("${spring.file.upload.base-path}")
    private String baseUploadPath;
    
    @Value("${spring.file.upload.base-url}")
    private String baseFileUrl;
    
    // 允许的图片类型
    private static final Set<String> ALLOWED_IMAGE_TYPES = new HashSet<>(Arrays.asList(
            "jpg", "jpeg", "png", "gif", "bmp", "webp"));
    
    // 允许的视频类型
    private static final Set<String> ALLOWED_VIDEO_TYPES = new HashSet<>(Arrays.asList(
            "mp4", "avi", "mov", "wmv", "flv", "mkv", "webm"));
    
    // 图片子目录
    private static final String IMAGE_SUB_DIR = "images";
    // 视频子目录
    private static final String VIDEO_SUB_DIR = "videos";
    
    /**
     * 上传单个图片文件
     * @param file 图片文件
     * @return 图片URL
     * @throws IOException 上传异常
     * @throws IllegalArgumentException 参数异常
     */
    public String uploadImage(MultipartFile file) throws IOException, IllegalArgumentException {
        validateFile(file, ALLOWED_IMAGE_TYPES, maxFileSize);
        return uploadFile(file, IMAGE_SUB_DIR);
    }
    
    /**
     * 上传单个图片文件（返回FileUploadResult对象）
     * @param image 图片文件
     * @return 上传结果对象，包含图片URL
     * @throws IOException 上传异常
     * @throws IllegalArgumentException 参数异常
     */
    public FileUploadResult uploadImageWithResult(MultipartFile image) throws IOException, IllegalArgumentException {
        String url = uploadImage(image);
        return new FileUploadResult(url);
    }
    
    /**
     * 上传多个图片文件
     * @param files 图片文件数组
     * @return 图片URL列表
     * @throws IOException 上传异常
     * @throws IllegalArgumentException 参数异常
     */
    public List<String> uploadImages(MultipartFile[] files) throws IOException, IllegalArgumentException {
        List<String> urls = new ArrayList<>();
        
        if (files == null || files.length == 0) {
            throw new IllegalArgumentException("请选择要上传的文件");
        }
        
        for (MultipartFile file : files) {
            validateFile(file, ALLOWED_IMAGE_TYPES, maxFileSize);
            urls.add(uploadFile(file, IMAGE_SUB_DIR));
        }
        
        return urls;
    }
    
    /**
     * 上传单个视频文件
     * @param file 视频文件
     * @return 视频URL
     * @throws IOException 上传异常
     * @throws IllegalArgumentException 参数异常
     */
    public String uploadVideo(MultipartFile file) throws IOException, IllegalArgumentException {
        validateFile(file, ALLOWED_VIDEO_TYPES, maxFileSize);
        return uploadFile(file, VIDEO_SUB_DIR);
    }
    
    /**
     * 验证文件是否符合要求
     */
    private void validateFile(MultipartFile file, Set<String> allowedTypes, Long maxSize) {
        if (file == null || file.isEmpty()) {
            throw new IllegalArgumentException("文件不能为空");
        }
        
        // 验证文件大小
        if (file.getSize() < minFileSize) {
            throw new IllegalArgumentException("文件太小");
        }
        
        if (file.getSize() > maxSize) {
            throw new IllegalArgumentException("文件大小超过限制");
        }
        
        // 验证文件类型
        String fileExtension = getFileExtension(file.getOriginalFilename());
        if (!allowedTypes.contains(fileExtension.toLowerCase())) {
            throw new IllegalArgumentException("不支持的文件类型");
        }
    }
    
    /**
     * 上传文件的核心方法
     */
    private String uploadFile(MultipartFile file, String subDir) throws IOException {
        // 生成唯一文件名
        String originalFilename = file.getOriginalFilename();
        String fileExtension = getFileExtension(originalFilename);
        String uniqueFilename = UUID.randomUUID().toString() + "." + fileExtension;
        
        // 创建日期目录结构
        String dateDir = generateDateDirectory();
        String fullDir = baseUploadPath + File.separator + subDir + File.separator + dateDir;
        
        // 确保目录存在
        File directory = new File(fullDir);
        if (!directory.exists()) {
            directory.mkdirs();
        }
        
        // 保存文件
        Path targetLocation = Paths.get(fullDir + File.separator + uniqueFilename);
        Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);
        
        // 生成可访问的URL
        String fileUrl = baseFileUrl + subDir + "/" + dateDir + "/" + uniqueFilename;
        logger.info("文件上传成功: {}", fileUrl);
        
        return fileUrl;
    }
    
    /**
     * 获取文件扩展名
     */
    private String getFileExtension(String filename) {
        if (filename == null || filename.isEmpty()) {
            return "";
        }
        
        int lastDotIndex = filename.lastIndexOf(".");
        if (lastDotIndex > 0 && lastDotIndex < filename.length() - 1) {
            return filename.substring(lastDotIndex + 1).toLowerCase();
        }
        
        return "";
    }
    
    /**
     * 生成日期目录结构（年/月/日）
     */
    private String generateDateDirectory() {
        LocalDate now = LocalDate.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
        return now.format(formatter);
    }
    
    /**
     * 根据文件ID获取文件访问URL
     * @param fileId 文件ID
     * @return 文件访问URL
     */
    public String getFileAccessUrl(String fileId) {
        if (fileId == null || fileId.isEmpty()) {
            return null;
        }
        
        // 如果fileId已经是完整的URL，直接返回
        if (fileId.startsWith("http://") || fileId.startsWith("https://")) {
            return fileId;
        }
        
        // 否则，构建完整的文件URL
        // 注意：这里假设fileId包含了相对路径，例如"images/2023/05/15/uuid.jpg"
        return baseFileUrl + fileId;
    }
    
    /**
     * 上传头像文件
     * @param avatar 头像文件
     * @return 上传后的文件名
     * @throws IOException 上传异常
     */
    public String uploadAvatar(MultipartFile avatar) throws IOException {
        validateFile(avatar, ALLOWED_IMAGE_TYPES, maxFileSize);
        return uploadFile(avatar, IMAGE_SUB_DIR);
    }
    
    /**
     * 删除图片文件
     * @param imagePath 图片路径或URL
     * @return 是否删除成功
     */
    public boolean deleteImage(String imagePath) {
        if (imagePath == null || imagePath.isEmpty()) {
            return false;
        }
        
        try {
            // 从URL中提取文件路径
            String filePath;
            if (imagePath.startsWith(baseFileUrl)) {
                filePath = imagePath.substring(baseFileUrl.length());
            } else {
                filePath = imagePath;
            }
            
            // 构建完整的文件系统路径
            String fullPath = baseUploadPath + File.separator + filePath;
            File file = new File(fullPath);
            
            // 检查文件是否存在并删除
            if (file.exists() && file.isFile()) {
                boolean deleted = file.delete();
                logger.info("文件删除{}, 路径: {}", deleted ? "成功" : "失败", fullPath);
                return deleted;
            } else {
                logger.warn("要删除的文件不存在: {}", fullPath);
                return false;
            }
        } catch (Exception e) {
            logger.error("删除文件失败: {}", e.getMessage());
            return false;
        }
    }
}
